package org.myspring;

import org.myspring.annotation.Component;
import org.myspring.annotation.ComponentScan;
import org.myspring.annotation.Conditional;
import org.myspring.annotation.Scope;

import java.beans.Introspector;
import java.io.File;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.List;

/**
 * beadDefinition的读取器
 *
 * @author shanzhenbo
 * @since 2023-06-16 17:02:30
 */
public class BeanDefinitionReader {

    /**
     * 其实就是MyAnnotationConfigApplicationContext
     */
    private BeanDefinitionRegistry registry;

    public void scan(Class<?>[] classes) {
        for (Class<?> clazz : classes) {
            scan(clazz);
        }
    }

    public BeanDefinitionReader(BeanDefinitionRegistry registry) {
        this.registry = registry;
    }


    private void scan(Class configClazz) {
        // 判断clazz是否有@MyComponentScan注解
        String locationPath = configClazz.getProtectionDomain().getCodeSource().getLocation().getPath();
        ComponentScan annotation = (ComponentScan) configClazz.getAnnotation(ComponentScan.class);
        if (annotation == null) {
            throw new RuntimeException("请添加@MyComponentScan注解");
        }
        // 获取注解的value值
        String path = annotation.value();
        // 扫描该包下的所有类
        String[] split = path.split(",");
        for (String s : split) {
            try {
                // 查找路径为s下的带有@MyComponent注解的类
                List<String> classNamesFromPath = getClassNamesFromPath(locationPath, s);

                for (String s1 : classNamesFromPath) {
                    Class<?> loadClass = Class.forName(s1);

                    if (!isConditionMatch(loadClass)) {
                        continue;
                    }

                    // 判断该类是否有@MyComponent注解
                    Component annotation1 = loadClass.getAnnotation(Component.class);
                    if (annotation1 != null) {
                        // 判断是否有实现BeanPostProcessor接口
                        if (BeanPostProcessor.class.isAssignableFrom(loadClass)) {
                            BeanPostProcessor beanPostProcessor = (BeanPostProcessor) loadClass.newInstance();
                            this.registry.addBeanPostProcessor(beanPostProcessor);
                        } else {
                            // 获取注解的value值
                            String beanName = annotation1.value();
                            if ("".equals(beanName)) {
                                // 获取默认的 beanName，格式是首字母小写
                                beanName = Introspector.decapitalize(loadClass.getSimpleName());
                            }

                            // 创建beanDefinition对象
                            BeanDefinition myBeanDefinition = new BeanDefinition(beanName, loadClass);

                            // 判断是否有@MyScope注解
                            if (loadClass.isAnnotationPresent(Scope.class)) {
                                Scope myComponent = loadClass.getAnnotation(Scope.class);
                                String scope = myComponent.value();
                                myBeanDefinition.setScope(scope);
                            }
                            // 存入map
                            this.registry.addBeadDefinition(beanName, myBeanDefinition);
                        }
                    }
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 判断是否满足条件，如果不满足需要跳过该类
     * @param loadClass
     * @return
     */
    private boolean isConditionMatch(Class<?> loadClass) {
        // 判断该类是否有@Condition注解
        if (loadClass.isAnnotationPresent(Conditional.class)) {
            Conditional conditional = loadClass.getAnnotation(Conditional.class);
            Class<? extends Condition>[] conditionClasses = conditional.value();

            List<Condition> conditionList = new ArrayList<>();
            // 获取所有的Condition实现类
            for (Class<? extends Condition> conditionClass : conditionClasses) {
                try {
                    conditionList.add(conditionClass.newInstance());
                } catch (InstantiationException | IllegalAccessException e) {
                    e.printStackTrace();
                }
            }

            // 判断是否满足条件
            for (Condition condition : conditionList) {
                if (!condition.matches(loadClass)) {
                    return false;
                }
            }
        }
        return true;
    }


    private List<String> getClassNamesFromPath(String locationPath, String path) {
        String oldPath = path;
        // 将包名转换为路径
        path = path.replace(".", "/");

        List<String> classNames = new ArrayList<>();
        File directory = new File(locationPath + path);
        if (directory.exists()) {
            File[] files = directory.listFiles();
            for (File file : files) {
                if (file.isFile() && file.getName().endsWith(".class")) {
                    String className = file.getName().substring(0, file.getName().length() - 6);
                    classNames.add(oldPath + "." + className);
                } else if (file.isDirectory()) {
                    String newPath = oldPath + "." + file.getName();
                    classNames.addAll(getClassNamesFromPath(locationPath, newPath));
                }
            }
        }
        return classNames;
    }
}
